package com.exigenservices.practice.roadcompanion.service;


import com.exigenservices.practice.roadcompanion.dao.PointsDAO;
import com.exigenservices.practice.roadcompanion.dao.UserInfoDAO;
import com.exigenservices.practice.roadcompanion.dao.UserRoutesDAO;
import com.exigenservices.practice.roadcompanion.dao.UsersDAO;
import com.exigenservices.practice.roadcompanion.entity.Points;
import com.exigenservices.practice.roadcompanion.entity.User;
import com.exigenservices.practice.roadcompanion.entity.UserInfo;
import com.exigenservices.practice.roadcompanion.entity.UserRoutes;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;


@Service
public class ServiceInterfaceImpl implements ServiceInterface {
    @Autowired
    private PointsDAO pointsDAO;
    @Autowired
    private UserRoutesDAO userRoutesDAO;
    @Autowired
    private UsersDAO usersDAO;
    @Autowired
    private UserInfoDAO userInfoDAO;

    @Override
    @Transactional
    public DUser getUser(long userId) throws Exception {

        User user = usersDAO.getUser(userId);
        return fillDUser(user);

    }

    @Transactional
    private DUser fillDUser(User user) throws Exception {
        UserInfo userInfo = null;
        userInfo = userInfoDAO.getUserInfo(user);

        List<UserRoutes> userRoutes = userRoutesDAO.getRoute(user);
        DUser dUser = new DUser(user, userInfo);
        for (UserRoutes routes : userRoutes) {
            List<Points> points = pointsDAO.getPoints(routes);
            dUser.addRoute(routes, points);
        }
        return dUser;
    }

    @Override
    @Transactional
    public DUser createUser(String login, String password) throws Exception {
        User user = new User();
        user.setLogin(login);
        user.setPassword(password);
        usersDAO.createUsers(user);
        long userId = user.getID();
        UserInfo userInfo = new UserInfo();
        userInfo.setUserID(userId);
        userInfoDAO.createUserInfo(userInfo);
        DUser dUser = new DUser(user, userInfo);
        return dUser;
    }

    @Override
    @Transactional
    public DUser getUserByLogin(String login) throws Exception {
        User user = usersDAO.getUser(login);
        return fillDUser(user);
    }

    @Override
    @Transactional
    public boolean saveUser(DUser dUser) throws Exception {
        User user = dUser.getUser();
        UserInfo userInfo = dUser.getUserInfo();
        usersDAO.updateUsers(user);

        userInfoDAO.updateUserInfo(userInfo);

        for (DRoute route : dUser.getRoutes()) {
            for (DPoint point : route.getPoints()) {
                pointsDAO.updatePoint(point.getPoints());
            }
            userRoutesDAO.updateUserRoute(route.getRoute());
        }
        return true;
    }

    @Override
    public boolean deleteUser(DUser dUser) throws Exception {
        User user = dUser.getUser();
        UserInfo userInfo = dUser.getUserInfo();
        usersDAO.deleteUsers(user);

        userInfoDAO.deleteUserInfo(userInfo);

        for (DRoute route : dUser.getRoutes()) {
            for (DPoint point : route.getPoints()) {
                pointsDAO.deletePoint(point.getPoints());
            }
            userRoutesDAO.deleteUserRoute(route.getRoute());
        }
        return true;
    }

    @Override
    @Transactional
    public boolean deleteRoute(DUser dUser, DRoute dRoute) throws Exception {
        Iterator<DRoute> it = dUser.getRoutes().iterator();
        while (it.hasNext()) {
            DRoute route = it.next();
            if (route == dRoute) {
                for (DPoint point : route.getPoints()) {
                    pointsDAO.deletePoint(point.getPoints());
                }
                userRoutesDAO.deleteUserRoute(route.getRoute());
                it.remove();
                return true;
            }
        }

        return false;
    }

    @Override
    @Transactional
    public boolean deletePoint(DRoute dRoute, DPoint dPoint) throws Exception {
        Iterator<DPoint> it = dRoute.getPoints().iterator();
        while (it.hasNext()) {
            DPoint point = it.next();
            if (point == dPoint) {
                pointsDAO.deletePoint(point.getPoints());
                it.remove();
                return true;
            }
        }
        return false;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    @Transactional
    public DRoute createRoute(DUser user) throws Exception {
        UserRoutes userRoutes = new UserRoutes();
        userRoutes.setUserID(user.getID());
        userRoutesDAO.createUserRoute(userRoutes);
        user.addRoute(userRoutes, new ArrayList<Points>());
        return new DRoute(userRoutes);
    }

    @Override
    @Transactional
    public DPoint createPoint(DRoute route) throws Exception {
        Points points = new Points();
        points.setRoute(route.getID());
        pointsDAO.createPoint(points);
        return route.addPoint(points);
    }


}
